home *** CD-ROM | disk | FTP | other *** search
/ Power Hacker 2003 / Power_Hacker_2003.iso / Exploit and vulnerability / w00w00 / sectools / dsniff / tcp_raw.c < prev    next >
Encoding:
C/C++ Source or Header  |  2000-05-18  |  4.8 KB  |  236 lines

  1. /*
  2.   tcp_raw.c
  3.  
  4.   Copyright (c) 2000 Dug Song <dugsong@monkey.org>
  5.   
  6.   $Id: tcp_raw.c,v 1.2 2000/05/18 20:40:33 dugsong Exp $
  7. */
  8.  
  9. #include "config.h"
  10. #include <sys/types.h>
  11. #include <sys/uio.h>
  12. #include <time.h>
  13. #ifdef HAVE_ERR_H
  14. #include <err.h>
  15. #endif
  16. #include <libnet.h>
  17. #include "options.h"
  18. #include "tcp_raw.h"
  19.  
  20. struct tha {
  21.     u_long            src;
  22.     u_long            dst;
  23.     u_long            port;
  24. };
  25.  
  26. struct tcp_seg {
  27.     u_long        seq;
  28.     u_char           *data;
  29.     int        len;
  30. };
  31.  
  32. struct tcp_conn {
  33.     struct tha        tha;
  34.     time_t            mtime;
  35.     struct tcp_seg           *seg;
  36.     int            segcnt;
  37.     int            segmax;
  38.     struct tcp_conn           *next;
  39. };
  40.  
  41. #define TCP_TIMEOUT    60
  42. #define TCP_HASHSIZE    919
  43.  
  44. static struct tcp_conn    conntab[TCP_HASHSIZE];
  45.  
  46. static int
  47. tcp_seg_compare(const void *a, const void *b)
  48. {
  49.     struct tcp_seg *sa, *sb;
  50.  
  51.     sa = (struct tcp_seg *) a;
  52.     sb = (struct tcp_seg *) b;
  53.  
  54.     if (sa->seq < sb->seq)
  55.         return (-1);
  56.     else if (sa->seq > sb->seq)
  57.         return (1);
  58.     else return (0);
  59. }
  60.  
  61. static void
  62. tcp_raw_delete(struct tcp_conn *conn)
  63. {
  64.     struct tcp_conn *hold;
  65.     int i;
  66.     
  67.     if (conn->next != NULL) {
  68.         for (i = 0; i < conn->segcnt; i++) {
  69.             if (conn->seg[i].data)
  70.                 free(conn->seg[i].data);
  71.         }
  72.         free(conn->seg);
  73.         conn->seg = NULL;
  74.         conn->segcnt = conn->segmax = 0;
  75.  
  76.         if (conn->next->next != NULL) {
  77.             hold = conn->next;
  78.             *conn = *conn->next;
  79.             free(hold);
  80.         }
  81.         else {
  82.             free(conn->next);
  83.             conn->next = NULL;
  84.         }
  85.     }
  86. }
  87.  
  88. static struct iovec *
  89. tcp_raw_reassemble(struct tcp_conn *conn, int minlen)
  90. {
  91.     struct iovec *iov;
  92.     int i, len;
  93.  
  94.     len = 0;
  95.     
  96.     for (i = 0; i < conn->segcnt; i++)
  97.         len += conn->seg[i].len;
  98.     
  99.     if (len < minlen)
  100.         return (NULL);
  101.  
  102.     if ((iov = calloc(1, sizeof(*iov))) == NULL)
  103.         err(1, "tcp_raw_input: calloc");
  104.     
  105.     qsort(conn->seg, conn->segcnt, sizeof(*conn->seg), tcp_seg_compare);
  106.  
  107.     for (i = 0; i < conn->segcnt; i++) {
  108.         len = conn->seg[i].len;
  109.         
  110.         if (iov->iov_base == NULL) {
  111.             if ((iov->iov_base = malloc(len)) == NULL)
  112.                 err(1, "tcp_raw_reassemble: malloc");
  113.         }
  114.         else {
  115.             iov->iov_base = realloc(iov->iov_base,
  116.                         iov->iov_len + len);
  117.             if (iov->iov_base == NULL)
  118.                 err(1, "tcp_raw_reassemble: realloc");
  119.         }
  120.         memcpy(iov->iov_base + iov->iov_len, conn->seg[i].data, len);
  121.         iov->iov_len += len;
  122.     }
  123.     return (iov);
  124. }
  125.  
  126. struct iovec *
  127. tcp_raw_input(struct ip *ip, struct tcphdr *tcp, int len)
  128. {
  129.     struct tha tha;
  130.     struct tcp_conn *conn;
  131.     struct tcp_seg seg;
  132.     struct iovec *iov;
  133.     u_short cksum;
  134.     u_char *buf;
  135.     int tcp_hl = tcp->th_off * 4;
  136.  
  137.     /* Verify TCP checksum. */
  138.     cksum = tcp->th_sum;
  139.     libnet_do_checksum((u_char *) ip, IPPROTO_TCP, len);
  140.  
  141.     if (cksum != tcp->th_sum)
  142.         return (NULL);
  143.  
  144.     tha.src = ip->ip_src.s_addr;
  145.     tha.dst = ip->ip_dst.s_addr;
  146.     tha.port = ntohs(tcp->th_sport) << 16 | ntohs(tcp->th_dport);
  147.     
  148.     buf = (u_char *)tcp + tcp_hl;
  149.     len -= tcp_hl;
  150.     iov = NULL;
  151.     
  152.     /* Find half-duplex stream associated with this segment. */
  153.     for (conn = &conntab[tha.port % TCP_HASHSIZE];
  154.          conn->next != NULL; conn = conn->next) {
  155.         if (memcmp((char *)&tha, (char *)&conn->tha, sizeof(tha)) == 0)
  156.             break;
  157.     }
  158.     /* Process by TCP flags. */
  159.     if (conn->next == NULL) {
  160.         if (tcp->th_flags & TH_SYN) {
  161.             if (conn->next == NULL) {
  162.                 if ((conn->next = (struct tcp_conn *)
  163.                      calloc(1, sizeof(*conn))) == NULL)
  164.                     err(1, "tcp_raw_input: calloc");
  165.             }
  166.             conn->tha = tha;
  167.  
  168.             if (conn->seg == NULL) {
  169.                 if ((conn->seg = (struct tcp_seg *)
  170.                      malloc(sizeof(seg) * 128)) == NULL)
  171.                     err(1, "tcp_raw_input: malloc");
  172.                 conn->segmax = 128;
  173.             }
  174.         }
  175.     }
  176.     else if (tcp->th_flags & TH_FIN || tcp->th_flags & TH_RST) {
  177.         iov = tcp_raw_reassemble(conn, 1);
  178.     }
  179.     else if (tcp->th_flags & TH_ACK && len > 0) {
  180.         if ((seg.data = (u_char *) malloc(len)) == NULL)
  181.             err(1, "tcp_raw_input: malloc");
  182.         memcpy(seg.data, buf, len);
  183.         seg.seq = ntohl(tcp->th_seq);
  184.         seg.len = len;
  185.         
  186.         if (conn->segcnt == conn->segmax) {
  187.             if ((conn->seg = (struct tcp_seg *)
  188.                  realloc(conn->seg, (conn->segmax * 2) *
  189.                      sizeof(seg))) == NULL)
  190.                 err(1, "tcp_raw_input: realloc");
  191.             conn->segmax *= 2;
  192.         }
  193.         conn->seg[conn->segcnt++] = seg;
  194.         
  195.         iov = tcp_raw_reassemble(conn, Opt_snaplen);
  196.     }
  197.     conn->mtime = time(NULL);
  198.     
  199.     /* If we successfully reassembled the stream, delete its entry. */
  200.     if (iov != NULL) {
  201.         tcp_raw_delete(conn);
  202.     }
  203.     return (iov);
  204. }
  205.  
  206. void
  207. tcp_raw_timeout(int timeout, tcp_raw_callback_t callback)
  208. {
  209.     struct tcp_conn *conn;
  210.     struct iovec *iov;
  211.     time_t now;
  212.     int i;
  213.  
  214.     now = time(NULL);
  215.     
  216.     for (i = 0; i < TCP_HASHSIZE; i++) {
  217.         for (conn = &conntab[i]; conn != NULL && conn->next != NULL;
  218.              conn = conn->next) {
  219.             if (now - conn->mtime > timeout) {
  220.                 iov = tcp_raw_reassemble(conn, 1);
  221.  
  222.                 if (iov != NULL) {
  223.                     callback(conn->tha.src, conn->tha.dst,
  224.                          conn->tha.port >> 16,
  225.                          conn->tha.port & 0xffff,
  226.                          iov->iov_base, iov->iov_len);
  227.                     free(iov->iov_base);
  228.                     free(iov);
  229.                 }
  230.                 tcp_raw_delete(conn);
  231.             }
  232.         }
  233.     }
  234. }
  235.  
  236.